package edu.yonsei.iwb.sdt.ontology;

import com.hp.hpl.jena.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;
import com.hp.hpl.jena.vocabulary.XSD;
import java.util.Vector;
import edu.yonsei.iwb.sdt.SDTLearner;
import edu.yonsei.iwb.ts.TSSearch;
import edu.yonsei.iwb.ts.model.ObjectNode;
import edu.yonsei.iwb.ts.model.Triple;
import java.io.IOException;
import java.util.ArrayList;

public class UnitClassModel {

    public static boolean BACKWARD = false;
    public static boolean FORWARD = true;
    private String centerclass;
    private Vector<String> dataTypeProperty;
    private Vector<PropertyArc> objectProperty;
    private Vector<String> uniqResource;
    
    public UnitClassModel(String r, int x){
        this.centerclass = r;
        this.dataTypeProperty = new Vector();
        this.objectProperty = new Vector();
    }
    
    public void addDatatypeProperty(String p){
        this.dataTypeProperty.add(p);
    }
    
    public void addObjectProperty(String p, boolean direction){
        this.objectProperty.add(new PropertyArc(p,direction));
    }

    public UnitClassModel(String r) throws IOException {
        this.centerclass = r;
        this.dataTypeProperty = new Vector();
        this.objectProperty = new Vector();
        this.uniqResource = new Vector();

        findConnectedProperty(r);
        ArrayList<ObjectNode> resit = TSSearch.listObjectNode(centerclass, RDFS.subClassOf.getURI());
        for (int i = 0; i < resit.size(); i++) {
            ObjectNode on = resit.get(i);
            String superclass = on.getValue();
            if (!UncountedResources.SET.contains(superclass)) {
                findConnectedProperty(superclass);
            }
        }
//        this.objectProperty.add(new PropertyArc("http://purl.org/procurement/public-contracts#awardedTender",UnitClassModel.FORWARD) );
//        this.dataTypeProperty.add("http://purl.org/dc/terms/type");
//        this.dataTypeProperty.add("http://purl.org/procurement/public-contracts#kind");
    }

    private void findConnectedProperty(String r) throws IOException {

        ArrayList<String> iter2 = TSSearch.listSubjectResource(RDFS.domain.getURI(), r);
        for (int i = 0; i < iter2.size(); i++) {
            String forwardp = iter2.get(i);
            if (UncountedResources.SET.contains(forwardp)) {
                continue;
            }


            ArrayList<Triple> iter3 = TSSearch.listTriple(forwardp, RDF.type.getURI(), OWL.DatatypeProperty.getURI());
            if (!iter3.isEmpty()) {
                if (!this.containsDatatypeProperty(forwardp)) {
                    this.dataTypeProperty.add(forwardp);
                }
            }

            ArrayList<Triple> iter4 = TSSearch.listTriple(forwardp, RDF.type.getURI(), OWL.ObjectProperty.getURI());

            if (!iter4.isEmpty()) {
                if (!this.containsObjectProperty(forwardp)) {
                    this.objectProperty.add(new PropertyArc(forwardp, UnitClassModel.FORWARD));
                }
            }

        }

        ArrayList<String> resi = TSSearch.listSubjectResource(RDFS.range.getURI(), r);
        for (int i = 0; i < resi.size(); i++) {
            String reversep = resi.get(i);
            if (UncountedResources.SET.contains(reversep)) {
                continue;
            }

            ArrayList<Triple> iter4 = TSSearch.listTriple(reversep, RDF.type.getURI(), OWL.ObjectProperty.getURI());
            if (!iter4.isEmpty()) {
                if (!this.containsObjectProperty(reversep)) {
                    this.objectProperty.add(new PropertyArc(reversep, UnitClassModel.BACKWARD));
                }
            }

        }

        if (SDTLearner.TARGETPROPERTY != null) {
            this.dataTypeProperty.remove(SDTLearner.TARGETPROPERTY);
        }
    }

    /**
     * for track a problem
     *
     * @param r
     * @param index
     * @throws IOException
     */
    private void findConnectedProperty(String r, int index) throws IOException {
        ArrayList<String> iter2 = TSSearch.listSubjectResource(RDFS.domain.getURI(), r);        
        for (int i = 0; i < iter2.size(); i++) {
            String forwardp = iter2.get(i);            
            if (UncountedResources.SET.contains(forwardp)) {
                continue;
            }

            ArrayList<ObjectNode> iter3 = TSSearch.listObjectNode(forwardp, RDFS.range.getURI());
            for (int j = 0; j < iter3.size(); j++) {
                ObjectNode range = iter3.get(j);
//                System.out.println(forwardp + " -- " + range.getValue());
                boolean flag = true;                
                if (range.getValue().startsWith(XSD.getURI())) {
                    if (!this.containsDatatypeProperty(forwardp)) {
                        this.dataTypeProperty.add(forwardp);
                        flag = false;
                    }
                    break;
                }

                if (flag) {
                    if (!this.containsObjectProperty(forwardp)) {
                        this.objectProperty.add(new PropertyArc(forwardp, UnitClassModel.FORWARD));
                        
                        ArrayList<String> itsu = TSSearch.listSubjectResource(RDFS.subPropertyOf.getURI(), forwardp);
                        for (int k = 0; k < itsu.size(); k++) {
                            String subp = itsu.get(k);
                            if (!UncountedResources.SET.contains(subp)) {
                                if (!this.containsObjectProperty(subp)) {
                                    this.objectProperty.add(new PropertyArc(subp, UnitClassModel.FORWARD));
                                }                                
                            }                
                        }
                        
                    }
                }
            }
        }
                        
        

        ArrayList<String> resi = TSSearch.listSubjectResource(RDFS.range.getURI(), r);
        for (int i = 0; i < resi.size(); i++) {
            String reversep = resi.get(i);
            if (!UncountedResources.SET.contains(reversep)) {
                if (!this.containsObjectProperty(reversep)) {
                    this.objectProperty.add(new PropertyArc(reversep, UnitClassModel.BACKWARD));
                    ArrayList<String> itsu = TSSearch.listSubjectResource(RDFS.subPropertyOf.getURI(), reversep);
                    for (int k = 0; k < itsu.size(); k++) {
                        String subp = itsu.get(k);
                        if (!UncountedResources.SET.contains(subp)) {
                            if (!this.containsObjectProperty(subp)) {
                                this.objectProperty.add(new PropertyArc(subp, UnitClassModel.BACKWARD));
                            }                                
                        }                
                    }
                }                
            }
        }        
        

        if (SDTLearner.TARGETPROPERTY != null) {
            this.dataTypeProperty.remove(SDTLearner.TARGETPROPERTY);
        }
    }

    public boolean containsObjectProperty(String r) {
        for (int i = 0; i < this.objectProperty.size(); i++) {
            PropertyArc pa = this.objectProperty.get(i);
            if (pa.equals(r)) {
                return true;
            }
        }
        return false;
    }

    public boolean containsDatatypeProperty(String r) {
        return this.dataTypeProperty.contains(r);
    }

    public Vector<String> getDatatypePropertySet() {
        return this.dataTypeProperty;
    }

    public Vector<PropertyArc> getObjectPropertySet() {
        return this.objectProperty;
    }

    public void printUnitClassModel() {
        System.out.println("Class : " + centerclass);
        for (int i = 0; i < this.dataTypeProperty.size(); i++) {
            System.out.println("Datatype Property : " + this.dataTypeProperty.get(i));
        }

        for (int i = 0; i < this.objectProperty.size(); i++) {
            System.out.println("Object Property : " + this.objectProperty.get(i));
        }
    }
}
